#ifndef ARCH_NABU_HCCA_H
#define ARCH_NABU_HCCA_H

#include <stdint.h>
#include <sys/compiler.h>

// Defines the read or write mode:
//
// HCCA_MODE_RB:  Reading mode uses a ringbuffer, this will wrap if you don't consume data
// HCCA_MODE_HDR: When reading, initally read a 3 byte header and extract the next block length from bytes 1 + 2
// HCCA_MODE_BLOCK: Read or write the block of memory passed into hcca_start_write()/hcca_start_read()
#define HCCA_MODE_RB    255
#define HCCA_MODE_HDR   0
#define HCCA_MODE_BLOCK 1


// Reset write buffers
extern void __LIB__ hcca_reset_write(void);

// Start the HCCA interrupt to begin writing
extern void __LIB__ hcca_start_write(uint8_t mode, void *buf, size_t buflen);

// Start the HCCA interrupt to start reading
// The supplied block is sent after any data generated by hcca_write* is written
extern void __LIB__ hcca_start_read(uint8_t mode, void *buf, size_t buflen);

// Blocks until all reading is complete
// Use this if the read mode is HCCA_MODE_HDR or HCCA_MODE_BLOCK
extern void __LIB__ hcca_read_wait_finished(void);

// Blocks until all writing is done
extern void __LIB__ hcca_write_wait_finished(void);

// **************************************************************************
// HCCA Receive
// ------------
// 
// These reading functions will block until data is available
// **************************************************************************

/// <summary>
/// Read a byte from the buffer.
/// </summary>
extern uint8_t __LIB__ hcca_readByte();

/// <summary>
/// Read an unsigned 16-bit integer from the HCCA
/// </summary>
extern uint16_t __LIB__ hcca_readUInt16();

/// <summary>
/// Read an signed 16-bit integer from the HCCA
/// </summary>
extern int16_t __LIB__ hcca_readInt16();

/// <summary>
/// Read an unsigned 32-bit integer from the HCCA
/// </summary>
extern uint32_t __LIB__ hcca_readUInt32();

/// <summary>
/// Read an signed 32-bit integer from the HCCA
/// </summary>
extern int32_t __LIB__ hcca_readInt32();

/// <summary>
/// Read bufferLen into buffer, starting at the offset
/// </summary>
extern void __LIB__ hcca_readBytes(uint8_t offset, uint8_t bufferLen, void *buffer);




// **************************************************************************
// HCCA Transmit
// -------------
// 
// These write functions fill up a buffer which is then transmitted when
// hcca_write_start() is called
// 
// **************************************************************************

/// <summary>
/// Write a byte to the HCCA
/// </summary>
extern void __LIB__ hcca_writeByte(uint8_t c);

/// <summary>
/// Write the unsigned 32-bit integer to the HCCA.
/// This is LSB First
/// </summary>
extern void __LIB__ hcca_writeUInt32(uint32_t val);

/// <summary>
/// Write the signed 32-bit integer to the HCCA.
/// This is LSB First
/// </summary>
extern void __LIB__ hcca_writeInt32(int32_t val);

/// <summary>
/// Write the unsigned 16-bit integer to the HCCA.
/// This is LSB First
/// </summary>
extern void __LIB__ hcca_writeUInt16(uint16_t val);

/// <summary>
/// Write the signed 16-bit integer to the HCCA.
/// This is LSB First
/// </summary>
extern void __LIB__ hcca_writeInt16(int16_t val);

/// <summary>
/// Write null terminated string to the HCCA
/// </summary>
extern void __LIB__ hcca_writeString(uint8_t* str);

/// <summary>
/// Write to the HCCA
/// </summary>
extern void __LIB__ hcca_writeBytes(uint16_t offset, uint16_t length, void *bytes);



#endif
